其他
Unite 2016|教你轻松玩转Shader
为了让更多没有接触过图形学的朋友也能很好的使用Shader,今天我们主要使用Unity专有的Surface Shader来进行展示,基本上只要填充好Surface函数即可。
想法其实很简单,就是让所有可能输出的颜色值都转化为有限的整数值。因为颜色值是范围0到1的小数,所以只要把颜色值乘以一个较大的整数,并把结果取整就可以把所有颜色值映射到固定的整数范围内了。假设角色纹理采样的颜色是Color,取整的最大整数为_Toon,我们进行颜色分级只要进行如下操作即可:floor(Color*_Toon)/_Toon。
颜色分级做好之后我们还需要做一个卡通风格的特征效果——描边。这里我们利用一个在Shader中常用的原理:在屏幕中我们看到的模型边缘处的法线方向,与我们当前视线方向的夹角是成90度的。这样我们就可以使用顶点法线方向与视线方向的点乘(点乘就是两个矢量的夹角cos值)来判断当前处理顶点是否边缘处。最后的Surface函数如下:
这样一个最简单的卡通渲染Shader就完成了。当然这个Shader还有很多改进空间,例如我们现在的做法无法控制边缘的宽度,并且边缘占用了模型本身的像素值,那么我们可以在一个新的Pass中把模型的顶点沿法线方向挤出,并只绘制背面来做一个新的边缘绘制效果,具体就由大家来实现啦。
想法很简单,我们对这个物体渲染两遍,第一个Pass设置渲染状态为像素被遮挡的时候才绘制,然后利用类似上面卡通渲染描边的方式做一个边缘发光的效果,第二个Pass正常渲染。最终的Shader如下:
上图第一个红框圈起来的Pass设置了ZTest greater的渲染状态,就是前面提到的和平常相反的像素剔除规则,然后在surf函数中用顶点法线方向与视线方向点乘的方式来做描边的效果。
其中_RimColor是自定义的描边颜色,_RimPower是用来加强边缘光效果的浮点数,另外编译指令#pragma后面加上alpha以表明我们需要用o.Alpha的值来与背景颜色进行半透明混合。然后在第二个正常渲染的Pass中我们用ZTest LEqual把像素剔除的规则还原回去再用基本的纹理着色方式来渲染。
代码非常简单,如下所示:
Unite 2016|Unity实时渲染动画电影《Gift》
今天的Shader教程就先介绍到这里,日后我们Unity官方工程师柳振东还将为大家分享更多有趣且实用的Shader。请关注Unity官方中文论坛(forum.china.unity3d.com)!